name: Blockscout

on:
  push:
    branches:
      - master
      - production-core
      - production-eth-experimental
      - production-eth-goerli
      - production-eth-sepolia
      - production-fuse
      - production-optimism
      - production-immutable
      - production-iota
      - production-lukso
      - production-rsk
      - production-sokol
      - production-suave
      - production-xdai
      - production-zkevm
      - production-zksync
      - staging-l2
    paths-ignore:
      - 'CHANGELOG.md'
      - '**/README.md'
      - 'docker/*'
      - 'docker-compose/*'
  pull_request:
    branches:
      - master
      - production-optimism

env:
  MIX_ENV: test
  OTP_VERSION: "25.2.1"
  ELIXIR_VERSION: "1.14.5"
  ACCOUNT_AUTH0_DOMAIN: "blockscoutcom.us.auth0.com"

jobs:
  matrix-builder:
    name: Build matrix
    runs-on: ubuntu-latest
    outputs:
      matrix: ${{ steps.set-matrix.outputs.matrix }}
    steps:
      - id: set-matrix
        run: |
          echo "matrix=$matrixStringifiedObject" >> $GITHUB_OUTPUT
        env:
          matrixStringifiedObject: '{"chain-type": ["ethereum", "polygon_edge", "polygon_zkevm", "rsk", "suave", "stability"]}'

  build-and-cache:
    name: Build and Cache deps
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: erlef/setup-beam@v1
        with:
          otp-version: ${{ env.OTP_VERSION }}
          elixir-version: ${{ env.ELIXIR_VERSION }}

      - name: "ELIXIR_VERSION.lock"
        run: echo "${ELIXIR_VERSION}" > ELIXIR_VERSION.lock

      - name: "OTP_VERSION.lock"
        run: echo "${OTP_VERSION}" > OTP_VERSION.lock

      - name: Restore Mix Deps Cache
        uses: actions/cache@v2
        id: deps-cache
        with:
          path: |
            deps
            _build
          key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_28-${{ hashFiles('mix.lock') }}
          restore-keys: |
            ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-

      - name: Conditionally build Mix deps cache
        if: steps.deps-cache.outputs.cache-hit != 'true'
        run: |
          mix local.hex --force
          mix local.rebar --force
          mix deps.get
          mix deps.compile

      - name: Restore Explorer NPM Cache
        uses: actions/cache@v2
        id: explorer-npm-cache
        with:
          path: apps/explorer/node_modules
          key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-explorer-npm-${{ hashFiles('apps/explorer/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-explorer-npm-

      - name: Conditionally build Explorer NPM Cache
        if: steps.explorer-npm-cache.outputs.cache-hit != 'true'
        run: npm install
        working-directory: apps/explorer

      - name: Restore Blockscout Web NPM Cache
        uses: actions/cache@v2
        id: blockscoutweb-npm-cache
        with:
          path: apps/block_scout_web/assets/node_modules
          key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-blockscoutweb-npm-${{ hashFiles('apps/block_scout_web/assets/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-blockscoutweb-npm-

      - name: Conditionally build Blockscout Web NPM Cache
        if: steps.blockscoutweb-npm-cache.outputs.cache-hit != 'true'
        run: npm install
        working-directory: apps/block_scout_web/assets

  credo:
    name: Credo
    runs-on: ubuntu-latest
    needs: build-and-cache
    steps:
      - uses: actions/checkout@v4
      - uses: erlef/setup-beam@v1
        with:
          otp-version: ${{ env.OTP_VERSION }}
          elixir-version: ${{ env.ELIXIR_VERSION }}

      - name: Restore Mix Deps Cache
        uses: actions/cache@v2
        id: deps-cache
        with:
          path: |
            deps
            _build
          key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_28-${{ hashFiles('mix.lock') }}
          restore-keys: |
            ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"

      - run: mix credo

  check_formatted:
    name: Code formatting checks
    runs-on: ubuntu-latest
    needs: build-and-cache
    steps:
      - uses: actions/checkout@v4
      - uses: erlef/setup-beam@v1
        with:
          otp-version: ${{ env.OTP_VERSION }}
          elixir-version: ${{ env.ELIXIR_VERSION }}

      - name: Restore Mix Deps Cache
        uses: actions/cache@v2
        id: deps-cache
        with:
          path: |
            deps
            _build
          key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_28-${{ hashFiles('mix.lock') }}
          restore-keys: |
            ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"

      - run: mix format --check-formatted

  dialyzer:
    strategy:
      fail-fast: false
      matrix: ${{ fromJson(needs.matrix-builder.outputs.matrix) }}
    name: Dialyzer static analysis
    runs-on: ubuntu-latest
    needs:
      - build-and-cache
      - matrix-builder
    steps:
      - uses: actions/checkout@v4
      - uses: erlef/setup-beam@v1
        with:
          otp-version: ${{ env.OTP_VERSION }}
          elixir-version: ${{ env.ELIXIR_VERSION }}

      - name: Restore Mix Deps Cache
        uses: actions/cache@v2
        id: deps-cache
        with:
          path: |
            deps
            _build
          key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_28-${{ hashFiles('mix.lock') }}
          restore-keys: |
            ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"

      - name: Restore Dialyzer Cache
        uses: actions/cache@v2
        id: dialyzer-cache
        with:
          path: priv/plts
          key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-${{ matrix.chain-type }}-dialyzer-mixlockhash_26-${{ hashFiles('mix.lock') }}
          restore-keys: |
            ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-${{ matrix.chain-type }}-dialyzer-"

      - name: Conditionally build Dialyzer Cache
        if: steps.dialyzer-cache.output.cache-hit != 'true'
        run: |
          mkdir -p priv/plts
          mix dialyzer --plt
        env:
          CHAIN_TYPE: ${{ matrix.chain-type }}

      - name: Run Dialyzer
        run: mix dialyzer --halt-exit-status
        env:
          CHAIN_TYPE: ${{ matrix.chain-type }}

  gettext:
    name: Missing translation keys check
    runs-on: ubuntu-latest
    needs: build-and-cache
    steps:
      - uses: actions/checkout@v4
      - uses: erlef/setup-beam@v1
        with:
          otp-version: ${{ env.OTP_VERSION }}
          elixir-version: ${{ env.ELIXIR_VERSION }}

      - name: Restore Mix Deps Cache
        uses: actions/cache@v2
        id: deps-cache
        with:
          path: |
            deps
            _build
          key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_28-${{ hashFiles('mix.lock') }}
          restore-keys: |
            ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"

      - run: |
          mix gettext.extract --merge | tee stdout.txt
          ! grep "Wrote " stdout.txt
        working-directory: "apps/block_scout_web"
  sobelow:
    name: Sobelow security analysis
    runs-on: ubuntu-latest
    needs: build-and-cache
    steps:
      - uses: actions/checkout@v4
      - uses: erlef/setup-beam@v1
        with:
          otp-version: ${{ env.OTP_VERSION }}
          elixir-version: ${{ env.ELIXIR_VERSION }}

      - name: Mix Deps Cache
        uses: actions/cache@v2
        id: deps-cache
        with:
          path: |
            deps
            _build
          key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_28-${{ hashFiles('mix.lock') }}
          restore-keys: |
            ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"

      - name: Scan explorer for vulnerabilities
        run: mix sobelow --config
        working-directory: "apps/explorer"
      - name: Scan block_scout_web for vulnerabilities
        run: mix sobelow --config
        working-directory: "apps/block_scout_web"

  cspell:
    name: Check spelling
    runs-on: ubuntu-latest
    needs: build-and-cache
    steps:
      - uses: actions/checkout@v4
      - uses: erlef/setup-beam@v1
        with:
          otp-version: ${{ env.OTP_VERSION }}
          elixir-version: ${{ env.ELIXIR_VERSION }}

      - name: Mix Deps Cache
        uses: actions/cache@v2
        id: deps-cache
        with:
          path: |
            deps
            _build
          key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_28-${{ hashFiles('mix.lock') }}
          restore-keys: |
            ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"

      - name: Restore Explorer NPM Cache
        uses: actions/cache@v2
        id: explorer-npm-cache
        with:
          path: apps/explorer/node_modules
          key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-explorer-npm-${{ hashFiles('apps/explorer/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-explorer-npm-

      - name: Restore Blockscout Web NPM Cache
        uses: actions/cache@v2
        id: blockscoutweb-npm-cache
        with:
          path: apps/block_scout_web/assets/node_modules
          key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-blockscoutweb-npm-${{ hashFiles('apps/block_scout_web/assets/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-blockscoutweb-npm-

      - name: Run cspell
        uses: streetsidesoftware/cspell-action@v2
        with:
          files: |
            **/*.ex*
            **/*.eex
            **/*.js"

  eslint:
    name: ESLint
    runs-on: ubuntu-latest
    needs: build-and-cache
    steps:
      - uses: actions/checkout@v4
      - uses: erlef/setup-beam@v1
        with:
          otp-version: ${{ env.OTP_VERSION }}
          elixir-version: ${{ env.ELIXIR_VERSION }}

      - name: Mix Deps Cache
        uses: actions/cache@v2
        id: deps-cache
        with:
          path: |
            deps
            _build
          key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_28-${{ hashFiles('mix.lock') }}
          restore-keys: |
            ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"

      - name: Restore Explorer NPM Cache
        uses: actions/cache@v2
        id: explorer-npm-cache
        with:
          path: apps/explorer/node_modules
          key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-explorer-npm-${{ hashFiles('apps/explorer/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-explorer-npm-

      - name: Restore Blockscout Web NPM Cache
        uses: actions/cache@v2
        id: blockscoutweb-npm-cache
        with:
          path: apps/block_scout_web/assets/node_modules
          key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-blockscoutweb-npm-${{ hashFiles('apps/block_scout_web/assets/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-blockscoutweb-npm-

      - name: Build assets
        run: node node_modules/webpack/bin/webpack.js --mode development
        working-directory: "apps/block_scout_web/assets"

      - run: ./node_modules/.bin/eslint --format=junit --output-file="test/eslint/junit.xml" js/**
        working-directory: apps/block_scout_web/assets
  jest:
    name: JS Tests
    runs-on: ubuntu-latest
    needs: build-and-cache
    steps:
      - uses: actions/checkout@v4
      - uses: erlef/setup-beam@v1
        with:
          otp-version: ${{ env.OTP_VERSION }}
          elixir-version: ${{ env.ELIXIR_VERSION }}

      - name: Mix Deps Cache
        uses: actions/cache@v2
        id: deps-cache
        with:
          path: |
            deps
            _build
          key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_28-${{ hashFiles('mix.lock') }}
          restore-keys: |
            ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"

      - name: Restore Blockscout Web NPM Cache
        uses: actions/cache@v2
        id: blockscoutweb-npm-cache
        with:
          path: apps/block_scout_web/assets/node_modules
          key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-blockscoutweb-npm-${{ hashFiles('apps/block_scout_web/assets/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-blockscoutweb-npm-

      - name: Build assets
        run: node node_modules/webpack/bin/webpack.js --mode development
        working-directory: "apps/block_scout_web/assets"

      - run: ./node_modules/.bin/jest
        working-directory: apps/block_scout_web/assets

  test_nethermind_mox_ethereum_jsonrpc:
    strategy:
      fail-fast: false
      matrix: ${{ fromJson(needs.matrix-builder.outputs.matrix) }}
    name: EthereumJSONRPC Tests
    runs-on: ubuntu-latest
    needs:
      - build-and-cache
      - matrix-builder
    services:
      postgres:
        image: postgres
        env:
          # Match apps/explorer/config/test.exs config :explorer, Explorer.Repo, database
          POSTGRES_DB: explorer_test
          # match PGPASSWORD for elixir image above
          POSTGRES_PASSWORD: postgres
          # match PGUSER for elixir image above
          POSTGRES_USER: postgres
        # Set health checks to wait until postgres has started
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          # Maps tcp port 5432 on service container to the host
          - 5432:5432
    steps:
      - uses: actions/checkout@v4
      - uses: erlef/setup-beam@v1
        with:
          otp-version: ${{ env.OTP_VERSION }}
          elixir-version: ${{ env.ELIXIR_VERSION }}

      - name: Mix Deps Cache
        uses: actions/cache@v2
        id: deps-cache
        with:
          path: |
            deps
            _build
          key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_28-${{ hashFiles('mix.lock') }}
          restore-keys: |
            ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"

      - run: ./bin/install_chrome_headless.sh
      - name: mix test --exclude no_nethermind
        run: |
          cd apps/ethereum_jsonrpc
          mix compile
          mix test --no-start --exclude no_nethermind
        env:
          # match POSTGRES_PASSWORD for postgres image below
          PGPASSWORD: postgres
          # match POSTGRES_USER for postgres image below
          PGUSER: postgres
          ETHEREUM_JSONRPC_CASE: "EthereumJSONRPC.Case.Nethermind.Mox"
          ETHEREUM_JSONRPC_WEB_SOCKET_CASE: "EthereumJSONRPC.WebSocket.Case.Mox"
          CHAIN_TYPE: "${{ matrix.chain-type }}"
  test_nethermind_mox_explorer:
    strategy:
      fail-fast: false
      matrix: ${{ fromJson(needs.matrix-builder.outputs.matrix) }}
    name: Explorer Tests
    runs-on: ubuntu-latest
    needs:
      - build-and-cache
      - matrix-builder
    services:
      postgres:
        image: postgres
        env:
          # Match apps/explorer/config/test.exs config :explorer, Explorer.Repo, database
          POSTGRES_DB: explorer_test
          # match PGPASSWORD for elixir image above
          POSTGRES_PASSWORD: postgres
          # match PGUSER for elixir image above
          POSTGRES_USER: postgres
        # Set health checks to wait until postgres has started
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          # Maps tcp port 5432 on service container to the host
          - 5432:5432
    steps:
      - uses: actions/checkout@v4
      - uses: erlef/setup-beam@v1
        with:
          otp-version: ${{ env.OTP_VERSION }}
          elixir-version: ${{ env.ELIXIR_VERSION }}

      - name: Mix Deps Cache
        uses: actions/cache@v2
        id: deps-cache
        with:
          path: |
            deps
            _build
          key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_28-${{ hashFiles('mix.lock') }}
          restore-keys: |
            ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"

      - name: Restore Explorer NPM Cache
        uses: actions/cache@v2
        id: explorer-npm-cache
        with:
          path: apps/explorer/node_modules
          key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-explorer-npm-${{ hashFiles('apps/explorer/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-explorer-npm

      - run: ./bin/install_chrome_headless.sh
      - name: mix test --exclude no_nethermind
        run: |
          mix ecto.create --quiet
          mix ecto.migrate
          cd apps/explorer
          mix compile
          mix test --no-start --exclude no_nethermind
        env:
          # match POSTGRES_PASSWORD for postgres image below
          PGPASSWORD: postgres
          # match POSTGRES_USER for postgres image below
          PGUSER: postgres
          ETHEREUM_JSONRPC_CASE: "EthereumJSONRPC.Case.Nethermind.Mox"
          ETHEREUM_JSONRPC_WEB_SOCKET_CASE: "EthereumJSONRPC.WebSocket.Case.Mox"
          CHAIN_TYPE: "${{ matrix.chain-type }}"
  test_nethermind_mox_indexer:
    strategy:
      fail-fast: false
      matrix: ${{ fromJson(needs.matrix-builder.outputs.matrix) }}
    name: Indexer Tests
    runs-on: ubuntu-latest
    needs:
      - build-and-cache
      - matrix-builder
    services:
      postgres:
        image: postgres
        env:
          # Match apps/explorer/config/test.exs config :explorer, Explorer.Repo, database
          POSTGRES_DB: explorer_test
          # match PGPASSWORD for elixir image above
          POSTGRES_PASSWORD: postgres
          # match PGUSER for elixir image above
          POSTGRES_USER: postgres
        # Set health checks to wait until postgres has started
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          # Maps tcp port 5432 on service container to the host
          - 5432:5432
    steps:
      - uses: actions/checkout@v4
      - uses: erlef/setup-beam@v1
        with:
          otp-version: ${{ env.OTP_VERSION }}
          elixir-version: ${{ env.ELIXIR_VERSION }}

      - name: Mix Deps Cache
        uses: actions/cache@v2
        id: deps-cache
        with:
          path: |
            deps
            _build
          key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_28-${{ hashFiles('mix.lock') }}
          restore-keys: |
            ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"

      - run: ./bin/install_chrome_headless.sh

      - name: mix test --exclude no_nethermind
        run: |
          mix ecto.create --quiet
          mix ecto.migrate
          cd apps/indexer
          mix compile
          mix test --no-start --exclude no_nethermind
        env:
          # match POSTGRES_PASSWORD for postgres image below
          PGPASSWORD: postgres
          # match POSTGRES_USER for postgres image below
          PGUSER: postgres
          ETHEREUM_JSONRPC_CASE: "EthereumJSONRPC.Case.Nethermind.Mox"
          ETHEREUM_JSONRPC_WEB_SOCKET_CASE: "EthereumJSONRPC.WebSocket.Case.Mox"
          CHAIN_TYPE: "${{ matrix.chain-type }}"
  test_nethermind_mox_block_scout_web:
    strategy:
      fail-fast: false
      matrix: ${{ fromJson(needs.matrix-builder.outputs.matrix) }}
    name: Blockscout Web Tests
    runs-on: ubuntu-latest
    needs:
      - build-and-cache
      - matrix-builder
    services:
      redis_db:
        image: "redis:alpine"
        ports:
          - 6379:6379

      postgres:
        image: postgres
        env:
          # Match apps/explorer/config/test.exs config :explorer, Explorer.Repo, database
          POSTGRES_DB: explorer_test
          # match PGPASSWORD for elixir image above
          POSTGRES_PASSWORD: postgres
          # match PGUSER for elixir image above
          POSTGRES_USER: postgres
        # Set health checks to wait until postgres has started
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          # Maps tcp port 5432 on service container to the host
          - 5432:5432
    steps:
      - uses: actions/checkout@v4
      - uses: erlef/setup-beam@v1
        with:
          otp-version: ${{ env.OTP_VERSION }}
          elixir-version: ${{ env.ELIXIR_VERSION }}

      - name: Mix Deps Cache
        uses: actions/cache@v2
        id: deps-cache
        with:
          path: |
            deps
            _build
          key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_28-${{ hashFiles('mix.lock') }}
          restore-keys: |
            ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"

      - name: Restore Explorer NPM Cache
        uses: actions/cache@v2
        id: explorer-npm-cache
        with:
          path: apps/explorer/node_modules
          key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-explorer-npm-${{ hashFiles('apps/explorer/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-explorer-npm-

      - name: Restore Blockscout Web NPM Cache
        uses: actions/cache@v2
        id: blockscoutweb-npm-cache
        with:
          path: apps/block_scout_web/assets/node_modules
          key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-blockscoutweb-npm-${{ hashFiles('apps/block_scout_web/assets/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-blockscoutweb-npm-

      - name: Build assets
        run: node node_modules/webpack/bin/webpack.js --mode development
        working-directory: "apps/block_scout_web/assets"

      - run: ./bin/install_chrome_headless.sh

      - name: mix test --exclude no_nethermind
        run: |
          mix ecto.create --quiet
          mix ecto.migrate
          cd apps/block_scout_web
          mix compile
          mix test --no-start --exclude no_nethermind
        env:
          # match POSTGRES_PASSWORD for postgres image below
          PGPASSWORD: postgres
          # match POSTGRES_USER for postgres image below
          PGUSER: postgres
          ETHEREUM_JSONRPC_CASE: "EthereumJSONRPC.Case.Nethermind.Mox"
          ETHEREUM_JSONRPC_WEB_SOCKET_CASE: "EthereumJSONRPC.WebSocket.Case.Mox"
          CHAIN_ID: "10200"
          API_RATE_LIMIT_DISABLED: "true"
          ADMIN_PANEL_ENABLED: "true"
          ACCOUNT_ENABLED: "true"
          ACCOUNT_REDIS_URL: "redis://localhost:6379"
          SOURCIFY_INTEGRATION_ENABLED: "true"
          CHAIN_TYPE: "${{ matrix.chain-type }}"
